home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / cpicker / color.c next >
C/C++ Source or Header  |  1995-06-22  |  5KB  |  280 lines

  1. /* $Header: color.c,v 1.2 88/06/30 09:58:36 mikey Exp $ */
  2.  
  3. /* 
  4.  * color.c - color helper routines
  5.  * 
  6.  * Author:    Christopher A. Kent
  7.  *         Western Research Laboratory
  8.  *         Digital Equipment Corporation
  9.  * Date:    Sun Dec 13 1987
  10.  * Copyright (c) 1987 Christopher A. Kent
  11.  */
  12.  
  13. /* 
  14.  * See David F. Rogers, "Procedural Elements for Computer Graphics",
  15.  * McGraw-Hill, for the theory behind these routines.
  16.  */
  17.  
  18. /*
  19.  * $Log:    color.c,v $
  20.  * Revision 1.2  88/06/30  09:58:36  mikey
  21.  * Handles CMY also.
  22.  * 
  23.  * Revision 1.1  88/06/30  09:10:32  mikey
  24.  * Initial revision
  25.  * 
  26.  */
  27.  
  28. static char rcs_ident[] = "$Header: color.c,v 1.2 88/06/30 09:58:36 mikey Exp $";
  29.  
  30. #include <X11/Xlib.h>
  31. #include "color.h"
  32.  
  33. #define    MAX_INTENSITY    65535                /* for X11 */
  34.  
  35. #define    MIN(a, b)   ((a)<(b)?(a):(b))
  36. #define    MAX(a, b)   ((a)>(b)?(a):(b))
  37. #define    ABS(x)        ((x)<0?-(x):(x))
  38.  
  39. RGB    RGBWhite = { MAX_INTENSITY, MAX_INTENSITY, MAX_INTENSITY };
  40. RGB    RGBBlack = { 0, 0, 0 };
  41.  
  42. /*
  43.  * Mix two RGBs, with scale factors alpha and beta, in RGB space.
  44.  */
  45.  
  46. RGB
  47. MixRGB(r, alpha, s, beta)
  48. RGB    r, s;
  49. float    alpha, beta;
  50. {
  51.     RGB    t;
  52.  
  53.     t.r = MAX(0, MIN(MAX_INTENSITY, (int)(alpha*(r.r) + beta*(s.r))));
  54.     t.g = MAX(0, MIN(MAX_INTENSITY, (int)(alpha*(r.g) + beta*(s.g))));
  55.     t.b = MAX(0, MIN(MAX_INTENSITY, (int)(alpha*(r.b) + beta*(s.b))));
  56.     return t;
  57. }
  58.  
  59. /*
  60.  * Mix two RGBs with scale factors alpha and beta, in HSV space.
  61.  */
  62.  
  63. RGB
  64. MixHSV(r, alpha, s, beta)
  65. RGB    r, s;
  66. float    alpha, beta;
  67. {
  68.     HSV    rr, ss, tt;
  69.  
  70.     rr = RGBToHSV(r);
  71.     ss = RGBToHSV(s);
  72.     tt.h = alpha*rr.h + beta*ss.h;
  73.     if (ABS(rr.h - ss.h) > 0.5) {
  74.         tt.h = tt.h + 0.5;
  75.         if (tt.h >= 1.0)
  76.             tt.h = tt.h - 1.0;
  77.     }
  78.     tt.s = alpha*rr.s + beta*ss.s;
  79.     tt.v = alpha*rr.v + beta*ss.v;
  80.     return HSVToRGB(tt);
  81. }
  82.  
  83. /*
  84.  * Convert an HSV to an RGB.
  85.  */
  86.  
  87. RGB
  88. HSVToRGB(hsv)
  89. HSV    hsv;
  90. {
  91.     RGB    rgb;
  92.     float    p, q, t, f;
  93.     int    i;
  94.     
  95.     if (hsv.s == 0.0)
  96.         rgb = PctToRGB(hsv.v, hsv.v, hsv.v);
  97.     else {
  98.         if (hsv.s > 1.0)
  99.             hsv.s = 1.0;
  100.         if (hsv.s < 0.0)
  101.             hsv.s = 0.0;
  102.         if (hsv.v > 1.0)
  103.             hsv.v = 1.0;
  104.         if (hsv.v < 0.0)
  105.             hsv.v = 0.0;
  106.         if (hsv.h >= 1.0)
  107.             hsv.h = 0.0;
  108.  
  109.         hsv.h = 6.0 * hsv.h;
  110.         i = (int) hsv.h;
  111.         f = hsv.h - (float) i;
  112.         p = hsv.v * (1.0 - hsv.s);
  113.         q = hsv.v * (1.0 - (hsv.s * f));
  114.         t = hsv.v * (1.0 - (hsv.s * (1.0 - f)));
  115.  
  116.         switch(i) {
  117.         case 0:    rgb = PctToRGB(hsv.v, t, p); break;
  118.         case 1:    rgb = PctToRGB(q, hsv.v, p); break;
  119.         case 2:    rgb = PctToRGB(p, hsv.v, t); break;
  120.         case 3:    rgb = PctToRGB(p, q, hsv.v); break;
  121.         case 4:    rgb = PctToRGB(t, p, hsv.v); break;
  122.         case 5:    rgb = PctToRGB(hsv.v, p, q); break;
  123.         }
  124.     }
  125.     return rgb;
  126. }
  127.  
  128. /*
  129.  * Convert an RGB to HSV.
  130.  */
  131.  
  132. HSV
  133. RGBToHSV(rgb)
  134. RGB    rgb;
  135.  
  136. {
  137.     HSV    hsv;
  138.     float    rr, gg, bb;
  139.     float    min, max;
  140.     float    rc, gc, bc;
  141.     
  142.     rr = (float) rgb.r / (float) MAX_INTENSITY;
  143.     gg = (float) rgb.g / (float) MAX_INTENSITY;
  144.     bb = (float) rgb.b / (float) MAX_INTENSITY;
  145.     
  146.     max = MAX(MAX(rr, gg), bb);
  147.     min = MIN(MIN(rr, gg), bb);
  148.     hsv.v = max;
  149.     if (max == 0.0)
  150.         hsv.s = 0.0;
  151.     else
  152.         hsv.s = (max - min) / max;
  153.     if (hsv.s == 0.0)
  154.         hsv.h = 0.0;
  155.     else {
  156.         rc = (max - rr) / (max - min);
  157.         gc = (max - gg) / (max - min);
  158.         bc = (max - bb) / (max - min);
  159.         if (rr == max)
  160.             hsv.h = bc - gc;
  161.         else if (gg == max)
  162.             hsv.h = 2.0 + rc - bc;
  163.         else if (bb = max)
  164.             hsv.h = 4.0 + gc - rc;
  165.  
  166.         if (hsv.h < 0.0)
  167.             hsv.h += 6.0;
  168.         hsv.h = hsv.h / 6.0;
  169.     }
  170.     return hsv;
  171. }
  172.  
  173. /*
  174.  * Intensity percentages to RGB.
  175.  */
  176.  
  177. RGB
  178. PctToRGB(rr, gg, bb)
  179. float    rr, gg, bb;
  180. {
  181.     RGB    rgb;
  182.     
  183.     if (rr > 1.0)
  184.         rr = 1.0;
  185.     if (gg > 1.0)
  186.         gg = 1.0;
  187.     if (bb > 1.0)
  188.         bb = 1.0;
  189.     
  190.     rgb.r = (int)(0.5 + rr * MAX_INTENSITY);
  191.     rgb.g = (int)(0.5 + gg * MAX_INTENSITY);
  192.     rgb.b = (int)(0.5 + bb * MAX_INTENSITY);
  193.     return rgb;
  194. }
  195.  
  196. /*
  197.  * Intensity percentages to HSV.
  198.  */
  199.  
  200. HSV
  201. PctToHSV(hh, ss, vv)
  202. float    hh, ss, vv;
  203. {
  204.     HSV    hsv;
  205.  
  206.     if (hh > 1.0)
  207.         hh = 1.0;
  208.     if (ss > 1.0)
  209.         ss = 1.0;
  210.     if (vv > 1.0)
  211.         vv = 1.0;
  212.  
  213.     hsv.h = hh;
  214.     hsv.s = ss;
  215.     hsv.v = vv;
  216.     return hsv;
  217. }
  218.  
  219. /*
  220.  * The Manhattan distance between two colors, between 0.0 and 3.0.
  221.  */
  222.  
  223. float
  224. RGBDist(r, s)
  225. RGB    r, s;
  226. {
  227.     return (
  228.         ABS((float)(r.r - s.r)) +
  229.         ABS((float)(r.g - s.g)) +
  230.         ABS((float)(r.b - s.b))) / (float)MAX_INTENSITY;
  231. }
  232.  
  233. /*
  234.  * Load an XColor with an RGB.
  235.  */
  236.  
  237. RGBToXColor(r, x)
  238. RGB    r;
  239. XColor    *x;
  240. {
  241.     x->red = r.r;
  242.     x->green = r.g;
  243.     x->blue = r.b;
  244.     x->flags = DoRed | DoGreen | DoBlue;
  245. }
  246.  
  247. /*
  248.  * Convert a CMY to RGB.
  249.  */
  250.  
  251. RGB
  252. CMYToRGB(cmy)
  253. CMY    cmy;
  254.  
  255. {
  256.     RGB    rgb;
  257.  
  258.     rgb.r = MAX_INTENSITY - cmy.c;
  259.     rgb.g = MAX_INTENSITY - cmy.m;
  260.     rgb.b = MAX_INTENSITY - cmy.y;
  261.     return rgb;
  262. }
  263.  
  264. /*
  265.  * Convert an RGB to CMY.
  266.  */
  267.  
  268. CMY
  269. RGBToCMY(rgb)
  270. RGB    rgb;
  271.  
  272. {
  273.     CMY    cmy;
  274.  
  275.     cmy.c = MAX_INTENSITY - rgb.r;
  276.     cmy.m = MAX_INTENSITY - rgb.g;
  277.     cmy.y = MAX_INTENSITY - rgb.b;
  278.     return cmy;
  279. }
  280.